package com.fzrskj.cloud.free.sys.utils;

import com.fzrskj.cloud.free.consts.AppCode;
import com.fzrskj.cloud.free.consts.CConsts;
import com.fzrskj.cloud.free.core.enums.DicParamEnum;
import com.fzrskj.cloud.free.core.tool.CMailParamVo;
import com.fzrskj.cloud.free.core.tool.CMailTool;
import com.fzrskj.cloud.free.core.utils.CloudContextUtils;
import com.fzrskj.cloud.free.dic.utils.DicParamUtils;
import com.fzrskj.cloud.free.sys.bean.*;
import com.fzrskj.cloud.free.sys.dao.CParamDao;
import com.fzrskj.cloud.free.sys.dao.SysNotifyRecordDao;
import com.fzrskj.cloud.free.sys.dao.SysNotifyTemplateDao;
import com.fzrskj.cloud.free.user.bean.UserAccountView;
import com.fzrskj.cloud.free.user.bean.UserIssue;
import com.fzrskj.cloud.free.user.utils.UserAccountUtils;
import com.fzrskj.cloud.free.user.utils.UserLogUtils;
import ms.core.consts.SysErr;
import ms.core.object.CObject;
import ms.core.tool.DateTimeTool;
import ms.core.tool.StrTool;
import ms.core.tool.XmlCodeParser;
import net.sf.json.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;

/**
 * SendMailUtils.
 *
 * @author zj.
 * Created on 2018/8/31 0031.
 */
public class SendMailUtils extends CObject {
    /**
     * to load notify template
     *
     * @param msgTypeValue
     * @return
     */
    private SysNotifyTemplate getNoitfyTemplate(String msgTypeValue) {
        SysNotifyTemplateDao tempDao = new SysNotifyTemplateDao();
        SysNotifyTemplate temp = tempDao.querySysNotifyTemplate(msgTypeValue);
        String code = tempDao.getErrCode();
        this.setErrCode(code);
        tempDao.dispose();
        return temp;
    }

    /**
     * to load mail parameter
     *
     * @return
     */
    private CMailParamVo getMailParam() {
        CDicUtils utls = new CDicUtils();
        int type = CloudContextUtils.getAgentId() == 0 ? 2 : 3;
        List<Param> params = utls.getParam(null, type);
        String code = utls.getErrCode();
        this.setErrCode(code);
        if (params == null) {
            return null;
        }

        CMailParamVo ret = new CMailParamVo();
        for (Param p : params) {
            if (null == p || null == p.getParamName()) {
                continue;
            }
            String pName = p.getParamName().toLowerCase();
            if (pName.equals("mailservice")) {
                ret.setMailHost(p.getParamValue());
            } else if (pName.endsWith("mailname")) {
                ret.setSender(p.getParamValue());
            } else if (pName.endsWith("mailpassword")) {
                ret.setPassword(p.getParamValue());
            } else if (pName.endsWith("mailport")) {
                ret.setPort(StrTool.strToIntDef(p.getParamValue(), 25));
            } else if (pName.endsWith("mailssl")) {
                ret.setSsl(StrTool.getDefaultValue(p.getParamValue(), "false"));
            }
        }
        if (null == ret.getSsl() || ret.getSsl().length()<1){
            ret.setSsl("false");
        }
        return ret;
    }

    /**
     * to load web site parameter
     *
     * @param params
     */
    public void loadWebsiteParam(List<NameValuePair> params) {
        CParamDao dao = new CParamDao();
        List<Param> pms = dao.queryParam(1, null);
        dao.dispose();
        if (params == null) {
            return;
        }

        for (Param p : pms) {
            String pcode = p.getParamName().toLowerCase();
            params.add(new BasicNameValuePair("\\[" + pcode + "\\]", p.getParamValue()));
        }
    }

    /**
     * to replace tag
     *
     * @param info
     * @param params
     * @return
     */
    private String replaceMailTag(String info, List<NameValuePair> params) {
        for (NameValuePair p : params) {
            info = info.replaceAll(p.getName(), p.getValue());
        }
        return info;
    }

    /**
     * to add notify_record
     *
     * @param temp
     * @param title
     * @param content
     * @param sender
     * @param receiver
     * @param sendOK
     * @return
     */
    public int addSysNotifyRecord(String temp, String title, String content, String sender, String receiver, boolean sendOK) {
        SysNotifyRecord rd = new SysNotifyRecord();
        rd.setTitle(title);
        rd.setContent(content);
        rd.setMsgType(1);
        rd.setTempName(temp);
        rd.setReceiver(receiver);
        rd.setSender(sender);
        rd.setSendTime(new Date());
        if (sendOK) {
            rd.setState(2);
        } else {
            rd.setState(1);
        }
        SysNotifyRecordDao dao = new SysNotifyRecordDao();
        int ret = dao.addSysNotifyRecord(rd);
        dao.dispose();
        return ret;
    }

    /**
     * to send mail by template of msgTypeValue.
     *
     * @param tempName
     * @param receiver
     * @param params
     * @return
     */
    public SendResult sendMail(String tempName, String receiver, List<NameValuePair> params) {
        SendResult sendResult = new SendResult();
        String message = "";
        try {
            //to get notify template
            SysNotifyTemplate temp = getNoitfyTemplate(tempName);
            if (temp == null) {
                sendResult.setCode(SysErr.SYS_MAIL_SEND_ERR);
                sendResult.setId(-1);
                sendResult.setMsg("获得邮件消息模板失败！");
                return sendResult;
            }
            //get mail parameter
            CMailParamVo param = this.getMailParam();
            if (param == null) {
                sendResult.setCode(SysErr.SYS_MAIL_SEND_ERR);
                sendResult.setId(-1);
                sendResult.setMsg("获得邮件参数失败！");
                return sendResult;
            }

            // replace params
            message = replaceMailTag(temp.getContent(), params);
            String subject = replaceMailTag(temp.getTitle(), params);
            String webname = DicParamUtils.getParamValue("webname");
            String comtel = DicParamUtils.getParamValue("comtel");
            String comfax = DicParamUtils.getParamValue("comfax");
            subject = subject.replace("[公司名]", webname);
            message = message.replace("[电话]", comtel);
            message = message.replace("[传真]", comfax);
            message = message.replace("[公司名]", webname);
            message = message.replaceAll("\\[template]", DicParamUtils.getParamValue(DicParamEnum.TEMPLATE_KEY.getVal()));
            message = message.replace("\n", "<br />");

            Mail mail = new Mail();
            mail.setAuth(true);
            mail.setHost(param.getMailHost());
            mail.setPort(param.getPort());
            mail.setSender(param.getSender());
            mail.setPassword(param.getPassword());
            mail.setSubject(subject);
            mail.setMessage(message);
            mail.setReceiver(receiver);
            mail.setSsl(param.getSsl());

            Map<String, Object> cdt = new HashMap<String, Object>();
            cdt.put("tempName", tempName);
            cdt.put("subject", subject);
            cdt.put("message", message);
            cdt.put("receiver", receiver);

//            System.out.println("sendEmail");
//            System.out.println("tempName:" + tempName);
//            System.out.println("subject:" + subject);
//            System.out.println("message:" + message);
//            System.out.println("receiver:" + receiver);
//            System.out.println();

            SendMailThread smt = new SendMailThread();
            smt.setMail(mail);
            smt.setThreadParam(cdt);
            Thread thread = new Thread(smt);
            thread.start();
        } catch (Exception e) {
            e.printStackTrace();
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw, true));
            SysRunTimeLogUtils.addLog(this, 10000, tempName, "发送报文=【" + message + "】,接收异常=【" + sw.toString() + "】");
        }
        return sendResult;
    }

    /**
     * to send mail by template of msgTypeValue.
     *
     * @param receiver
     * @param subject
     * @param message
     * @return
     */
    private SendResult bathSend(String receiver, String subject, String message) {
        SendResult sendResult = new SendResult();
        Exception error = null;
        boolean sendOK = false;
        try {
            // get mail parameter
            CMailParamVo param = this.getMailParam();
            if (param == null) {
                sendResult.setCode(SysErr.SYS_MAIL_SEND_ERR);
                sendResult.setId(-1);
                sendResult.setMsg("获得邮件参数失败！");
                return sendResult;
            }

            Mail mail = new Mail();
            mail.setAuth(true);
            mail.setHost(param.getMailHost());
            mail.setPort(param.getPort());
            mail.setSender(param.getSender());
            mail.setPassword(param.getPassword());
            mail.setSubject(subject);
            mail.setMessage(message);
            mail.setReceiver(receiver);
            mail.setSsl(param.getSsl());
            String sendState;
            //JSONObject result = JSONObject.fromObject(MailTool.sendMail(mail));
            System.out.println("mail = " + JSONObject.fromObject(mail).toString());
            System.out.println("sendOK=" + sendOK);
            sendOK = CMailTool.sendMail(mail);
            if (!sendOK) {
                UserLogUtils.addLog(this, 0, "sendMail", "发送失败=【发送失败】，接收者邮箱【" + receiver + "】");
                sendState = SysErr.SYS_MAIL_SEND_ERR;
                sendOK = false;
            } else {
                sendState = SysErr.CODE_SUCCESS;
                sendOK = true;
            }
            addSysNotifyRecord(subject, subject, message, mail.getSender(), receiver, sendOK);
            sendResult.setCode(sendState);
            sendResult.setId(!sendOK ? 0 : -1);
            sendResult.setMsg(XmlCodeParser.codeOfMessage(sendState));
        } catch (Exception ex) {
            error = ex;
            ex.printStackTrace();
            StringWriter sw = new StringWriter();
            ex.printStackTrace(new PrintWriter(sw, true));
            SysRunTimeLogUtils.addLog(this, 1000, "bathSend", "发送报文=【" + message + "】,接收异常=【" + sw.toString() + "】");
        } finally {
            if (!sendOK) {
                UserLogUtils.addLog(this, null == CloudContextUtils.getSession() ?
                                CloudContextUtils.getAdminId() : CloudContextUtils.getSession().getUID(),
                        "发送报文=【" + message + "】,，异常信息【" + error + "】");
            }
        }
        return sendResult;
    }

    /*================================== SendMail Service processing module  ============================================*/

    /**
     * to send active mail email to user by userId
     *
     * @param uid
     * @return
     */
    private SendResult sendActiveAccount(int uid) {
        SendResult ret = new SendResult();
        //load user account info
        UserAccountUtils uaUtils = new UserAccountUtils();
        UserAccountView uv = uaUtils.queryUserAccountViewByUid(uid);
        String code = uaUtils.getErrCode();
        if (!code.equals(SysErr.CODE_SUCCESS)) {
            ret.setCode(SysErr.DB_UNKNOWN_ERR);
            ret.setId(-1);
            ret.setMsg(XmlCodeParser.codeOfMessage(SysErr.DB_UNKNOWN_ERR));
            return ret;
        }
        if (uv == null) {
            ret.setCode(SysErr.USER_NOT_EXISTS);
            ret.setId(-1);
            ret.setMsg(XmlCodeParser.codeOfMessage(SysErr.USER_NOT_EXISTS));
            return ret;
        }
        if (uv.getStatus().equals(CConsts.ACCOUNT_NORMAL)) {
            ret.setCode(AppCode.USER_ACTIVED);
            ret.setId(-1);
            ret.setMsg(XmlCodeParser.codeOfMessage(AppCode.USER_ACTIVED));
            return ret;
        }

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        loadWebsiteParam(params);
        params.add(new BasicNameValuePair("\\[uid\\]", String.format("%s", uv.getUserId())));
        params.add(new BasicNameValuePair("\\[code\\]", uv.getRandomCode()));

        return sendMail("registerEmail", uv.getEmail(), params);
    }

    /**
     * to send confirm_mod_success mail email to user by userId
     *
     * @param uid
     * @return
     */
    private SendResult sendAccountModPass(int uid) {
        SendResult ret = new SendResult();
        //load user account info
        UserAccountUtils uaUtils = new UserAccountUtils();
        UserAccountView uv = uaUtils.queryUserAccountViewByUid(uid);
        String code = uaUtils.getErrCode();
        if (!code.equals(SysErr.CODE_SUCCESS)) {
            ret.setCode(SysErr.DB_UNKNOWN_ERR);
            ret.setId(-1);
            ret.setMsg(XmlCodeParser.codeOfMessage(SysErr.DB_UNKNOWN_ERR));
            return ret;
        }
        if (uv == null) {
            ret.setCode(SysErr.USER_NOT_EXISTS);
            ret.setId(-1);
            ret.setMsg(XmlCodeParser.codeOfMessage(SysErr.USER_NOT_EXISTS));
            return ret;
        }

        //create mod_passsword_time
        Date date = new Date();
        String modTime = DateTimeTool.formatDateTime(date, "yyyy-MM-dd HH:mm:ss");

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        loadWebsiteParam(params);
        params.add(new BasicNameValuePair("\\[时间\\]", modTime));

        return sendMail("findPswEmail", uv.getEmail(), params);
    }

    /**
     * to send issue mail email to user by userId
     *
     * @param queryDetails
     * @return
     */
    private SendResult sendIssue(UserIssue queryDetails) {
        //create mod_passsword_time
        Date date = new Date();
        String modTime = DateTimeTool.formatDateTime(date, "yyyy-MM-dd HH:mm:ss");

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        loadWebsiteParam(params);
        params.add(new BasicNameValuePair("\\[时间\\]", modTime));
        params.add(new BasicNameValuePair("\\[工单号\\]", String.valueOf(queryDetails.getParentIssueId())));
        params.add(new BasicNameValuePair("\\[工单标题\\]", String.valueOf(queryDetails.getBusinessName())));

        return sendMail("woWaitConfirmEmail", queryDetails.getEmail(), params);
    }

    private SendResult sendIssueToAdmin(UserIssue queryDetails) {
        String dateTime = DateTimeTool.formatDateTime(queryDetails.getIssueTime(), "yyyy-MM-dd HH:mm:ss");

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        loadWebsiteParam(params);
        params.add(new BasicNameValuePair("\\[会员名称\\]", queryDetails.getUserName()));
        params.add(new BasicNameValuePair("\\[时间\\]", dateTime));

        return sendMail("adminReceiveWorkOrderEmail", DicParamUtils.getParamValue("workOrderEmail"), params);
    }

    /*============================================= public static functions =================================================*/

    /**
     * send mail with identify template
     *
     * @param msgTypeValue = sys_notify_template.msgTypeValue
     * @param receiver     email receiver
     * @param params       parameters of replacing template tag
     * @return
     */
    public static SendResult sendNotifyMail(String msgTypeValue, String receiver, List<NameValuePair> params) {
        SendMailUtils mail = new SendMailUtils();
        return mail.sendMail(msgTypeValue, receiver, params);
    }

    /**
     * send active account mail by uid & email
     *
     * @param uid user Id
     * @return
     */
    public static SendResult sendActiveAccountMail(int uid) {
        SendMailUtils mail = new SendMailUtils();
        return mail.sendActiveAccount(uid);
    }

    /**
     * @return
     * @ send confirm_mod_success mail by uid & email
     */
    public static SendResult sendAccountModPassMail(int uid) {
        SendMailUtils mail = new SendMailUtils();
        return mail.sendAccountModPass(uid);
    }

    /**
     * @return
     * @ send issue mail by uid & email
     */
    public static SendResult sendIssueMail(UserIssue issue) {
        SendMailUtils mail = new SendMailUtils();
        return mail.sendIssue(issue);
    }

    /**
     * @return
     * @ send issue mail by uid & email
     */
    public static SendResult sendIssueToAdminMail(UserIssue issue) {
        SendMailUtils mail = new SendMailUtils();
        return mail.sendIssueToAdmin(issue);
    }

    /**
     * @return
     * @ send  mail by receiver & subject & subject
     */
    public static SendResult bathSendMail(String receiver, String subject, String message) {
        SendMailUtils mail = new SendMailUtils();
        return mail.bathSend(receiver, subject, message);
    }
}
